package com.sssre.lttcloud.framework.service.impl;

import com.sssre.lttcloud.common.result.Result;
import com.sssre.lttcloud.common.result.ResultCode;
import com.sssre.lttcloud.common.utils.RedisUtil;
import com.sssre.lttcloud.framework.service.PerformanceMonitorService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 性能监测服务实现类
 */
@Service
public class PerformanceMonitorServiceImpl implements PerformanceMonitorService {

    @Autowired
    private RedisUtil redisUtil;

    private static final String METHOD_STATS_PREFIX = "perf:stats:";
    private static final String METHOD_HISTORY_PREFIX = "perf:history:";
    private static final String SLOW_QUERY_PREFIX = "perf:slow:";
    private static final String TIMEOUT_PREFIX = "perf:timeout:";
    private static final String METHOD_START_PREFIX = "perf:start:";

    @Override
    public void recordMethodStart(String methodName, String description, Object[] params) {
        try {
            String key = METHOD_START_PREFIX + methodName + ":" + System.currentTimeMillis();
            Map<String, Object> data = new HashMap<>();
            data.put("methodName", methodName);
            data.put("description", description);
            data.put("startTime", System.currentTimeMillis());
            data.put("params", params != null ? Arrays.toString(params) : "");
            
            redisUtil.hmset(key, data, 3600); // 1小时过期
        } catch (Exception e) {
            // 记录日志但不影响业务
            System.err.println("记录方法开始失败: " + e.getMessage());
        }
    }

    @Override
    public void recordMethodEnd(String methodName, long executionTime, boolean success, String failedMessage, Object result) {
        try {
            // 更新统计信息
            updateMethodStats(methodName, executionTime, success);
            
            // 记录历史
            recordMethodHistory(methodName, executionTime, success, failedMessage, result);
            
            // 如果是慢查询，记录到慢查询列表
            if (executionTime > 1000) { // 超过1秒认为是慢查询
                recordSlowQuery(methodName, executionTime, failedMessage);
            }
        } catch (Exception e) {
            System.err.println("记录方法结束失败: " + e.getMessage());
        }
    }

    @Override
    public void recordTimeout(String methodName, long executionTime, long timeout) {
        try {
            String key = TIMEOUT_PREFIX + methodName + ":" + System.currentTimeMillis();
            Map<String, Object> data = new HashMap<>();
            data.put("methodName", methodName);
            data.put("executionTime", executionTime);
            data.put("timeout", timeout);
            data.put("timestamp", System.currentTimeMillis());
            data.put("datetime", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            
            redisUtil.hmset(key, data, 86400); // 24小时过期
        } catch (Exception e) {
            System.err.println("记录超时失败: " + e.getMessage());
        }
    }

    @Override
    public Result<Map<String, Object>> getPerformanceStats() {
        try {
            Map<String, Object> stats = new HashMap<>();
            
            // 获取所有方法的统计信息
            Set<String> keys =  redisUtil.sGet(METHOD_STATS_PREFIX + "*").stream().map(Objects::toString).collect(Collectors.toSet());
            if (keys != null) {
                for (String key : keys) {
                    String methodName = key.replace(METHOD_STATS_PREFIX, "");
                    Map<Object, Object> methodStats = redisUtil.hmget(key);
                    stats.put(methodName, methodStats);
                }
            }
            
            return Result.success(stats);
        } catch (Exception e) {
            return Result.failed(ResultCode.FAILED, "获取性能统计失败: " + e.getMessage());
        }
    }

    @Override
    public Result<List<Map<String, Object>>> getMethodHistory(String methodName, int limit) {
        try {
            List<Map<String, Object>> history = new ArrayList<>();
            String pattern = METHOD_HISTORY_PREFIX + methodName + ":*";
            
            // 这里简化处理，实际应该使用Redis的ZRANGE等命令
            // 由于RedisUtils没有提供按模式查询的方法，这里只是示例
            String key = METHOD_HISTORY_PREFIX + methodName + ":latest";
            Map<Object, Object> latest = redisUtil.hmget(key);
            if (latest != null) {
                Map<String, Object> historyItem = new HashMap<>();
                for (Map.Entry<Object, Object> entry : latest.entrySet()) {
                    historyItem.put(entry.getKey().toString(), entry.getValue());
                }
                history.add(historyItem);
            }
            
            return Result.success(history);
        } catch (Exception e) {
            return Result.failed(ResultCode.FAILED, "获取方法历史失败: " + e.getMessage());
        }
    }

    @Override
    public Result<List<Map<String, Object>>> getSlowQueries(long threshold) {
        try {
            List<Map<String, Object>> slowQueries = new ArrayList<>();
            String pattern = SLOW_QUERY_PREFIX + "*";
            
            // 简化处理，实际应该使用Redis的SCAN命令
            // 这里只是示例实现
            String key = SLOW_QUERY_PREFIX + "latest";
            Map<Object, Object> latest = redisUtil.hmget(key);
            if (latest != null) {
                Map<String, Object> slowQuery = new HashMap<>();
                for (Map.Entry<Object, Object> entry : latest.entrySet()) {
                    slowQuery.put(entry.getKey().toString(), entry.getValue());
                }
                slowQueries.add(slowQuery);
            }
            
            return Result.success(slowQueries);
        } catch (Exception e) {
            return Result.failed(ResultCode.FAILED, "获取慢查询失败: " + e.getMessage());
        }
    }

    @Override
    public Result<String> clearHistoryData(int days) {
        try {
            // 清理指定天数前的数据
            long cutoffTime = System.currentTimeMillis() - (days * 24 * 60 * 60 * 1000L);
            
            // 这里应该实现清理逻辑，但由于RedisUtils的限制，只是示例
            // 实际应该使用Redis的SCAN和DEL命令
            
            return Result.success("清理完成");
        } catch (Exception e) {
            return Result.failed(ResultCode.FAILED, "清理历史数据失败: " + e.getMessage());
        }
    }

    // 私有方法
    private void updateMethodStats(String methodName, long executionTime, boolean success) {
        String key = METHOD_STATS_PREFIX + methodName;
        
        // 更新调用次数
        redisUtil.hincr(key, "totalCalls", 1);
        
        // 更新成功次数
        if (success) {
            redisUtil.hincr(key, "successCalls", 1);
        } else {
            redisUtil.hincr(key, "errorCalls", 1);
        }
        
        // 更新总执行时间
        redisUtil.hincr(key, "totalTime", executionTime);
        
        // 更新平均执行时间
        Object totalCalls = redisUtil.hget(key, "totalCalls");
        Object totalTime = redisUtil.hget(key, "totalTime");
        if (totalCalls != null && totalTime != null) {
            double avgTime = Double.parseDouble(totalTime.toString()) / Double.parseDouble(totalCalls.toString());
            redisUtil.hset(key, "avgTime", avgTime);
        }
        
        // 更新最大执行时间
        Object maxTime = redisUtil.hget(key, "maxTime");
        if (maxTime == null || executionTime > Double.parseDouble(maxTime.toString())) {
            redisUtil.hset(key, "maxTime", executionTime);
        }
        
        // 更新最小执行时间
        Object minTime = redisUtil.hget(key, "minTime");
        if (minTime == null || executionTime < Double.parseDouble(minTime.toString())) {
            redisUtil.hset(key, "minTime", executionTime);
        }
        
        // 设置过期时间（7天）
        redisUtil.expire(key, 7 * 24 * 60 * 60);
    }

    private void recordMethodHistory(String methodName, long executionTime, boolean success, String errorMessage, Object result) {
        String key = METHOD_HISTORY_PREFIX + methodName + ":latest";
        Map<String, Object> data = new HashMap<>();
        data.put("methodName", methodName);
        data.put("executionTime", executionTime);
        data.put("success", success);
        data.put("errorMessage", errorMessage != null ? errorMessage : "");
        data.put("result", result != null ? result.toString() : "");
        data.put("timestamp", System.currentTimeMillis());
        data.put("datetime", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        
        redisUtil.hmset(key, data, 86400); // 24小时过期
    }

    private void recordSlowQuery(String methodName, long executionTime, String failedMessage) {
        String key = SLOW_QUERY_PREFIX + "latest";
        Map<String, Object> data = new HashMap<>();
        data.put("methodName", methodName);
        data.put("executionTime", executionTime);
        data.put("failedMessage", failedMessage != null ? failedMessage : "");
        data.put("timestamp", System.currentTimeMillis());
        data.put("datetime", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        
        redisUtil.hmset(key, data, 86400); // 24小时过期
    }
} 